package com.horizon.common.util;

import lombok.extern.slf4j.Slf4j;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 数字类型工具类
 *
 * @author wangfuwei
 * @version 2018-08-05
 */
@Slf4j
public class NumberUtil {

    /**
     * 格式化数字
     *
     * @param value
     * @param pattern
     * @return
     */
    public static String format(Object value, String pattern) {
        String res = null;
        if (pattern == null || pattern.isEmpty())
            pattern = "###,##0.00";
        if (value == null)
            value = 0;
        DecimalFormat df = new DecimalFormat(pattern);
        try {
            if (value instanceof String) {
                res = df.format(new Double(value.toString()));
            } else {
                res = df.format(value);
            }
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 保留指定位数
     *
     * @param value
     * @param digit
     * @return
     */
    public static Number round(Object value, Integer digit) {
        String digitString = "0";
        for (int i = 1; i < digit; i++) {
            digitString += "0";
        }
        if (value == null)
            value = 0;

        Number res = null;
        DecimalFormat df = new DecimalFormat("0." + digitString);
        try {
            if (value instanceof String) {
                res = Double.valueOf(df.format(new Double(value.toString())));
            } else {
                res = Double.valueOf(df.format(value));
            }
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }

        return res;
    }

    /**
     * 执行javascript公式
     *
     * @param js 需要执行的js公式
     * @return 执行结果
     */
    public static Object exeJsFormula(String js) {
        return exeJsFormula(js, null);
    }

    /**
     * 执行javascript公式
     *
     * @param js       需要执行的js公式
     * @param paramMap 公式中的参数列表
     * @return 执行结果
     * @throws ScriptException
     */
    public static Object exeJsFormula(String js, Map<String, Object> paramMap) {
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("JavaScript");
        if (paramMap != null && paramMap.size() > 0) {
            for (String key : paramMap.keySet()) {
                scriptEngine.put(key, paramMap.get(key));
            }
        }
        try {
            return scriptEngine.eval(js);
        } catch (Exception e) {
            log.error("执行JS方法失败:{} - {}", js, paramMap, e);
        }
        return null;
    }

    /**
     * 校验值是否为整数
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isInt(Object value) {
        return exePattern(value, "^-?\\d+$");
    }

    /**
     * 校验值是否为浮点数
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isFloat(Object value) {
        return exePattern(value, "^(-?\\d+)(\\.\\d+)?$");
    }

    /**
     * 校验值是否为正整数(非0)
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isPosInt(Object value) {
        return exePattern(value, "^\\+?[1-9][0-9]*$");
    }

    /**
     * 校验值是否为负整数(非0)
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isNegInt(Object value) {
        return exePattern(value, "^\\-[1-9][0-9]*$");
    }

    /**
     * 校验值是否为非负整数(0+正整数)
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isNotNegInt(Object value) {
        return exePattern(value, "^\\d+$");
    }

    /**
     * 校验值是否为非正整数(0+负整数)
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isNotPosInt(Object value) {
        return exePattern(value, "^((-\\d+)|(0+))$");
    }

    /**
     * 校验值是否为正浮点数(非0)
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isPosFloat(Object value) {
        return exePattern(value, "^(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*))$");
    }

    /**
     * 校验值是否为负浮点数(非0)
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isNegFloat(Object value) {
        return exePattern(value, "^(-(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*)))$");
    }

    /**
     * 校验值是否为非负浮点数(0+正浮点数)
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isNotNegFloat(Object value) {
        return exePattern(value, "^\\d+(\\.\\d+)?$");
    }

    /**
     * 校验值是否为非正浮点数(0+负浮点数)
     *
     * @param {} value 需要校验的值
     */
    public static Boolean isNotPosFloat(Object value) {
        return exePattern(value, "^((-\\d+(\\.\\d+)?)|(0+(\\.0+)?))$");
    }

    /**
     * 校验值最多保留n位小数
     *
     * @param value 需要校验的值
     * @param point 保留point位小数
     */
    public static Boolean isPoint(Object value, Integer point) {
        return exePattern(value, "^-?\\d+\\.?\\d{0," + point + "}$");
    }

    /**
     * 小写金额转大写
     *
     * @param n 需要转大写的数字
     * @return
     */
    public static String uppercase(Double n) {
        String fraction[] = {"角", "分"};
        String digit[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        String unit[][] = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}};
        String head = n < 0 ? "负" : "";
        n = Math.abs(n);
        String s = "";
        for (int i = 0; i < fraction.length; i++) {
            s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
        }
        if (s.length() < 1) {
            s = "整";
        }
        int integerPart = (int) Math.floor(n);
        for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
            String p = "";
            for (int j = 0; j < unit[1].length && n > 0; j++) {
                p = digit[integerPart % 10] + unit[1][j] + p;
                integerPart = integerPart / 10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }

    /**
     * 执行正则表达式
     *
     * @param value      需要比较的值
     * @param patternStr 正则表达式
     * @return
     */
    private static Boolean exePattern(Object value, String patternStr) {
        if (value == null || value.toString().isEmpty()) {
            return false;
        }
        String valueStr = value.toString();
        if (valueStr.indexOf(".") != -1 && valueStr.indexOf("E") != -1) {
            BigDecimal bd = new BigDecimal(valueStr);
            valueStr = bd.toPlainString();
        }
        Pattern pattern = Pattern.compile(patternStr);
        Matcher matcher = pattern.matcher(valueStr);
        return matcher.matches();
    }
}